import { SearchOutlined } from '@ant-design/icons'
import { keywordCompare } from '@gnlab/utils'
import { useRefValue } from '@gnlab/utils/env-react'
import { Tag, Button, Input } from 'antd'
import { EditModal, Empty } from '@/desktop/components'
import { useStreams } from '@/lib/utils'
import services from '@/services'
import type { GroupTag } from '@/services/contact-types'
import './index.module.less'

export default function ChooseGroupTags(props: {
  visible: boolean
  title?: string // 对话框标题
  choosed?: number[] | null // 已经选中的标签 id
  onSwitch?: (tag: GroupTag, choosed: boolean) => void // 某个标签被选中 / 取消选中时会触发此回调
  // 指定此回调代表上级会在每次更新时执行对应业务逻辑，而不是在 onFinish() 时一次性执行，因此界面上将不再显示“取消”按钮
  onFinish: (choosed?: GroupTag[]) => void // 结束选择时会触发此回调，未传入 "choosed" 说明用户执行了“取消”
}) {
  const { visible, title, choosed, onSwitch, onFinish } = props

  return <EditModal
    title={title ?? '选择标签'}
    width="600px"
    open={visible}
    onCancel={() => onFinish()}
  >
    {visible ? <ModalContent choosed={choosed} onSwitch={onSwitch} onFinish={onFinish} /> : null}
  </EditModal>
}

function ModalContent(props: {
  choosed?: number[] | null
  onSwitch?: (tag: GroupTag, choosed: boolean) => void
  onFinish: (choosed?: GroupTag[]) => void
}) {
  const { choosed: initialChoosed = [], onSwitch, onFinish } = props
  const [allTags] = useStreams(services.groups.tags)
  useEffect(() => void services.groups.loadTags(), [])

  const [choosed, setChoosed] = useState(() => new Set(initialChoosed))
  const choosedRef = useRefValue(choosed)

  const switchTag = useCallback(
    (tag: GroupTag) => {
      const { id } = tag
      const next = new Set(choosedRef.current)
      const nextChoosed = !next.has(id)
      if (next.has(id)) next.delete(id)
      else next.add(id)
      setChoosed(next)
      if (onSwitch) onSwitch(tag, nextChoosed)
    },
    [choosedRef, onSwitch],
  )

  const submit = useCallback(() => {
    onFinish(
      [...choosed].map(id => allTags.find(t => t.id === id)).filter((t): t is GroupTag => !!t),
    )
  }, [allTags, choosed, onFinish])

  const [keyword, setKeyword] = useState('')
  const filteredTags = useMemo(() => {
    const trimed = keyword.trim()
    return trimed ? allTags.filter(tag => keywordCompare(trimed, tag.name)) : allTags
  }, [allTags, keyword])

  return <>
    <div styleName="search">
      <Input
        placeholder="搜索标签"
        prefix={<SearchOutlined />}
        value={keyword}
        onChange={e => setKeyword(e.target.value)}
      />
    </div>

    <div styleName="tags">
      {!filteredTags.length ? <Empty description="没有可选的标签" /> : null}

      {filteredTags.map(tag => <Tag
        key={tag.id}
        onClick={() => switchTag(tag)}
        {...(choosed.has(tag.id) ? { color: '#4798EF' } : {})}
      >
        {tag.name}
      </Tag>)}
    </div>

    <footer>
      {!onSwitch ? <Button onClick={() => onFinish()}>取消</Button> : null}
      <Button type="primary" onClick={submit}>
        确定
      </Button>
    </footer>
  </>
}
